package com.xipu.yygh.manage.controller;

import com.xipu.yygh.common.exception.YyghException;
import com.xipu.yygh.common.result.R;
import com.xipu.yygh.common.result.Result;
import com.xipu.yygh.hosp.service.HospitalSetService;
import com.xipu.yygh.manage.service.DepartmentService;
import com.xipu.yygh.manage.service.HospManageService;
import com.xipu.yygh.manage.service.ScheduleService;
import com.xipu.yygh.model.hosp.Department;
import com.xipu.yygh.model.hosp.Hospital;
import com.xipu.yygh.model.hosp.Schedule;
import com.xipu.yygh.vo.hosp.DepartmentQueryVo;
import com.xipu.yygh.vo.hosp.ScheduleQueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * description: 医院管理接口
 * @author: gql
 * @date: 2022/04
 */
@RequestMapping("/api/hosp")
@RestController
public class HospManageController {

    /**
     * 排班表(MongoDB)
     */
    @Autowired
    private ScheduleService scheduleService;

    /**
     * 部门表(MongoDB)
     */
    @Autowired
    private DepartmentService departmentService;

    /**
     * 医院表(MongoDB)
     */
    @Autowired
    private HospManageService hospManageService;

    /**
     * 医院设置表(MySQL)
     */
    @Autowired
    private HospitalSetService hospitalSetService;

    //*************************排班接口*************************

    /**
     * 删除排班
     * @param request 请求
     * @return r
     */
    @PostMapping("/schedule/remove")
    public Result scheduleRemove(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);
        if (checkOutSignKey(map)) {
            return Result.fail().message("签名校验失败!");
        } else {
            this.scheduleService.scheduleRemove(map);
            return Result.ok();
        }
    }

    /**
     * 查询排班信息(条件查询带分页)
     * @param request 请求
     * @return r
     */
    @PostMapping("/schedule/list")
    public Result scheduleList(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);
        if (checkOutSignKey(map)) {
            return Result.fail().message("签名校验失败!");
        } else {
            /**
             * 准备分页数据信息
             * departmentQueryVo 查询条件
             * page:当前页
             * limit:每页记录数
             */
            ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
            String hoscode = (String) map.get("hoscode");
            String depcode = (String) map.get("depcode");
            scheduleQueryVo.setDepcode(depcode);
            scheduleQueryVo.setHoscode(hoscode);
            int page = StringUtils.isEmpty(map.get("page")) ? 1 : Integer.parseInt((String) map.get("page"));
            int limit = StringUtils.isEmpty(map.get("limit")) ? 10 : Integer.parseInt((String) map.get("limit"));

            // 6.执行查询排班操作
            Page<Schedule> pages = scheduleService.selectPage(page, limit, scheduleQueryVo);
            return Result.ok(pages);
        }
    }

    /**
     * 上传排班信息
     * @param request 请求
     * @return r
     */
    @PostMapping("/saveSchedule")
    public Result saveSchedule(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);
        if (checkOutSignKey(map)) {
            return Result.fail().message("签名校验失败!");
        } else {
            this.scheduleService.saveSchedule(map);
            return Result.ok();
        }
    }


    //*************************部门接口*************************

    /**
     * 删除部门信息
     * @param request 请求
     * @return r
     */
    @PostMapping("/department/remove")
    public Result departmentRemove(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);
        if (checkOutSignKey(map)) {
            return Result.fail().message("签名校验失败!");
        } else {
            String hoscode = (String) map.get("hoscode");
            String depcode = (String) map.get("depcode");
            this.departmentService.departmentRemove(hoscode, depcode);
            return Result.ok();
        }
    }

    /**
     * 查询部门信息
     * @param request 请求
     * @return r
     */
    @PostMapping("/department/list")
    public Result departmentList(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);
        if (checkOutSignKey(map)) {
            return Result.fail().message("签名校验失败!");
        } else {
            /**
             * 准备分页数据信息
             * departmentQueryVo 查询条件
             * page:当前页
             * limit:每页记录数
             */
            DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
            departmentQueryVo.setHoscode((String) map.get("depcode"));
            departmentQueryVo.setHoscode((String) map.get("hoscode"));
            int page = StringUtils.isEmpty(map.get("page")) ? 1 : Integer.parseInt((String) map.get("page"));
            int limit = StringUtils.isEmpty(map.get("limit")) ? 10 : Integer.parseInt((String) map.get("limit"));

            // 执行查询科室操作
            Page<Department> pages = departmentService.findPageDepartment(page, limit, departmentQueryVo);
            return Result.ok(pages);
        }
    }

    /**
     * 上传部门信息
     * @param request i请求
     * @return r
     */
    @PostMapping("/saveDepartment")
    public Result saveDepartment(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);
        if (checkOutSignKey(map)) {
            return Result.fail().message("签名校验失败!");
        } else {
            this.departmentService.saveDepartment(map);
            return Result.ok();
        }
    }

    //***********************医院接口***************************

    /**
     * 查询医院接口
     * @return r
     */
    @PostMapping("/hospital/show")
    public Result hospitalShow(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);
        String hoscode = (String) map.get("hoscode");
        if (checkOutSignKey(map)) {
            return Result.fail().message("签名校验失败!");
        } else {
            Hospital hospital = this.hospManageService.getHospital(hoscode);
            return Result.ok(hospital);
        }
    }

    /**
     * 医院上传接口：
     *      接收院方发来的HttpClient请求,并保存医院信息到MongoDB中
     *      1. 将Map<String, String[]> 变成 Map<String, Object>
     *      2. 将 Map<String, Object>中的值加到MongoDB中
     * @param request 请求
     * @return 上传成功或失败
     */
    @PostMapping("/saveHospital")
    public R saveHospital(HttpServletRequest request) {
        Map<String, Object> map = switchMap(request);

        if (checkOutSignKey(map)) {
            return R.error().message("签名校验失败");
        } else {
            // 传递的图片涉及base64编码问题，需要将logoData记录中所有的" "替换为+
            String logoData = (String) map.get("logoData");
            logoData = logoData.replaceAll(" ", "+");
            map.put("logoData", logoData);
            this.hospManageService.saveHosp(map);
            return R.ok().code(200);
        }
    }

    //*************************Utils*************************

    /**
     * SignKey签名校验: 医院传递过来的 eq 平台的
     * @param map 请求转换成的map对象
     * @return 校验是否成功
     */
    private boolean checkOutSignKey(Map<String, Object> map) {
        String signKeyA = (String) map.get("sign");
        String hoscode = (String) map.get("hoscode");
        if (StringUtils.isEmpty(hoscode)) {
            throw new YyghException(20001, "参数错误");
        }
        String signKeyB = this.hospitalSetService.getSignKey(hoscode);
        return !signKeyA.equals(DigestUtils.md5DigestAsHex(signKeyB.getBytes()));
    }

    /**
     * 将Map<String, String[]> 转换为 Map<String, Object>
     * @param request 请求
     * @return Map<String, Object>
     */
    private Map<String, Object> switchMap(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> map = new HashMap<>(16);
        parameterMap.forEach((key, value) -> map.put(key, value[0]));
        return map;
    }
}
